﻿namespace Hopfield.Simulator
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Globalization;
    using System.Reflection;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;

    public partial class MainForm : Form
    {
        #region Field

        List<TabPage> tabPages = new List<TabPage>();

        #endregion

        #region Constructor

        public MainForm()
        {
            this.Hopfield = global::Hopfield.Math.Hopfield.Instance;

            InitializeComponent();

            InitTabPages();
        }

        #endregion

        #region Properties

        Hopfield.Math.Hopfield hopfield = null;

        public Hopfield.Math.Hopfield Hopfield
        {
            get { return this.hopfield; }
            private set { this.hopfield = value; }
        }

        #endregion

        #region Methods

        private void PluginLoadType(Type type, Assembly assembly)
        {
            foreach (Attribute attr in type.GetCustomAttributes(false))
            {
                if (attr is HopfieldSimulatorPageAttribute)
                {
                    HopfieldSimulatorPageAttribute hattr = attr as HopfieldSimulatorPageAttribute;

                    UserControl pageControl = assembly.CreateInstance(
                        type.FullName,
                        true,
                        BindingFlags.CreateInstance,
                        null,
                        new object[] {global::Hopfield.Math.Hopfield.Instance,
                                      this.toolStripStatusLabelInfo,
                                      this.toolStripStatusLabelInfoMSE,
                                      this},
                        Thread.CurrentThread.CurrentCulture,
                        null) as UserControl;

                    IHopfieldSimulatorPage hopfieldPage = null;

                    if (pageControl == null ||
                       (hopfieldPage = pageControl as IHopfieldSimulatorPage) == null) continue;

                    TabPage tabPage = new TabPage(hattr.Name);

                    tabPage.Controls.Add(pageControl);
                    pageControl.Dock = DockStyle.Fill;

                    hopfieldPage.ChangedAttractorList += (sender, e) =>
                    {
                        this.RefreshTabPages();
                    };

                    this.tabPages.Add(tabPage);
                }
            }
        }

        private void InitTabPages()
        {
            this.tabPages.Clear();

            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (true == assembly.FullName.ToLower().Contains("hopfield.simulator"))
                {
                    foreach (Type type in assembly.GetTypes())
                    {
                        this.PluginLoadType(type, assembly);
                    }
                    continue;
                }

                if (false == assembly.FullName.ToLower().Contains("hopfield.plugin.")) continue;

                foreach (Type type in assembly.GetTypes())
                {
                    this.PluginLoadType(type, assembly);
                }
            }

            this.mainTabControl.TabPages.Clear();
            this.tabPages.Sort(new Comparison<TabPage>((x, y) => x.Text.CompareTo(y.Text)));
            foreach (TabPage tabPage in tabPages)
            {
                this.mainTabControl.TabPages.Add(tabPage);
            }

            this.mainTabControl.Selected += (sender, e) =>
            {
                this.RefreshMenu();

                if (this.SelectedSimulatorPage == null) return;
                this.SelectedSimulatorPage.Activate();
            };

            this.RefreshMenu();

            if (this.SelectedSimulatorPage == null) return;
            this.SelectedSimulatorPage.Activate();
        }

        private IHopfieldSimulatorPage SelectedSimulatorPage
        {
            get
            {
                if (this.mainTabControl.SelectedTab == null ||
                    this.mainTabControl.SelectedTab.Controls.Count == 0) return null;

                return this.mainTabControl.SelectedTab.Controls[0] as IHopfieldSimulatorPage;
            }
        }

        #endregion

        #region File

        private void toolStripMenuItemFileOpen_Click(object sender, EventArgs e)
        {
            if (this.SelectedSimulatorPage == null) return;
            this.SelectedSimulatorPage.FileOpen();
        }

        private void toolStripMenuItemFileSave_Click(object sender, EventArgs e)
        {
            if (this.SelectedSimulatorPage == null) return;
            this.SelectedSimulatorPage.FileSave();
        }

        #endregion

        #region Simulator

        private void toolStripMenuItemSimulatorLearn_Click(object sender, EventArgs e)
        {
            if (this.SelectedSimulatorPage == null) return;
            this.SelectedSimulatorPage.SimulatorLearn();
        }

        private void toolStripMenuItemSimulatorSimulate_Click(object sender, EventArgs e)
        {
            if (this.SelectedSimulatorPage == null) return;
            this.SelectedSimulatorPage.SimulatorSimulate();
        }

        #endregion

        #region Attractors

        private void toolStripMenuItemAttractorsAdd_Click(object sender, EventArgs e)
        {
            if (this.SelectedSimulatorPage == null) return;
            SelectedSimulatorPage.AttractorAdd();
        }

        private void toolStripMenuItemAttractorsRemoveSelected_Click(object sender, EventArgs e)
        {
            if (this.SelectedSimulatorPage == null) return;
            this.SelectedSimulatorPage.AttractorRemoveSelected();
        }

        #endregion

        #region TabPages

        private void RefreshTabPages()
        {
            if (SelectedSimulatorPage == null) return;

            TabPage selectedTabPage = this.mainTabControl.SelectedTab;

            if (this.Hopfield.LCount > 0)
            {
                foreach (TabPage tabPage in this.tabPages)
                {
                    if (tabPage.Text.CompareTo(selectedTabPage.Text) != 0)
                    {
                        this.mainTabControl.TabPages.Remove(tabPage);
                    }
                }
            }
            else
            {
                foreach (TabPage tabPage in this.tabPages)
                {
                    if (this.mainTabControl.TabPages.Contains(tabPage)) continue;

                    if (tabPage.Text.CompareTo(selectedTabPage.Text) < 0)
                    {
                        this.mainTabControl.TabPages.Insert(this.mainTabControl.TabPages.IndexOf(selectedTabPage), tabPage);
                    }
                    else
                    {
                        this.mainTabControl.TabPages.Add(tabPage);
                    }
                }
            }
        }

        private void CheckMenuMethod(string nameMethod, ToolStripMenuItem menuItem)
        {
            if (SelectedSimulatorPage == null) return;

            menuItem.Visible = true;

            foreach (Attribute attr in SelectedSimulatorPage
                                       .GetType()
                                       .GetMethod(nameMethod)
                                       .GetCustomAttributes(false))
            {
                if (attr is HopfieldSimulatorHideAttribute)
                {
                    menuItem.Visible = false;
                }
            }
        }

        private void RefreshMenu()
        {
            this.CheckMenuMethod("FileOpen", toolStripMenuItemFileOpen);
            this.CheckMenuMethod("FileSave", toolStripMenuItemFileSave);
            this.CheckMenuMethod("SimulatorLearn", toolStripMenuItemSimulatorLearn);
            this.CheckMenuMethod("SimulatorSimulate", toolStripMenuItemSimulatorSimulate);
            this.CheckMenuMethod("AttractorAdd", toolStripMenuItemAttractorsAdd);
            this.CheckMenuMethod("AttractorRemoveSelected", toolStripMenuItemAttractorsRemoveSelected);
        }

        #endregion
    }
}
